package com.spring.demo8.eg1.factory;

import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.core.AttributeAccessor;
import org.springframework.core.ResolvableType;
import org.springframework.lang.Nullable;

/**
 * BeanDefinition:bean定义信息的接口
 *
 * @author vhans
 */
public interface MyBeanDefinition extends AttributeAccessor, BeanMetadataElement {

    /**
     * 设置此bean的父bean名称（对应项目xml中bean元素的parent属性）
     */
    void setParentName(@Nullable String parentName);

    /**
     * 返回此bean定义时指定的父bean名称
     */
    @Nullable
    String getParentName();

    /**
     * 指定此bean定义的class类名（对应xml中bean元素的class属性）
     */
    void setBeanClassName(@Nullable String beanClassName);

    /**
     * 返回此bean定义的当前bean类名
     * <p>
     * 注意，如果子定义重写/继承其父类的类名，则这不一定是运行时使用的实际类名。
     * 此外，这可能只是调用工厂方法的类，或者在调用方法的工厂bean引用的情况下，
     * 它甚至可能是空的。因此，不要认为这是运行时的最终bean类型，而只将其用于
     * 单个bean定义级别的解析目的。
     */
    @Nullable
    String getBeanClassName();

    /**
     * 设置此bean的生命周期，如：singleton、prototype（对应xml中bean元素的scope属性）
     */
    void setScope(@Nullable String scope);

    /**
     * 返回此bean的生命周期
     */
    @Nullable
    String getScope();

    /**
     * 设置是否延迟初始化此bean（对应xml中bean元素的lazy属性）
     */
    void setLazyInit(boolean lazyInit);

    /**
     * 返回是否延迟初始化此bean，只对单例bean有效
     */
    boolean isLazyInit();

    /**
     * 设置此bean初始化依赖的bean的名称，bean工厂将保障dependsOn指定的bean会在当前bean初始化之前创建好
     */
    void setDependsOn(@Nullable String... dependsOn);

    /**
     * 返回此bean所依赖的bean名称
     */
    @Nullable
    String[] getDependsOn();

    /**
     * 设置此bean是否作为其他bean自动注入时的候选者
     */
    void setAutowireCandidate(boolean autowireCandidate);

    /**
     * 返回此bean是否作为其他bean自动注入时的候选者
     */
    boolean isAutowireCandidate();

    /**
     * 设置此bean是否为自动注入的主要候选者
     */
    void setPrimary(boolean primary);

    /**
     * 返回此bean是否为自动注入的主要候选者
     */
    boolean isPrimary();

    /**
     * 指定要使用的bean工厂（如果有）（对应xml中bean元素的factory-bean元素）
     */
    void setFactoryBeanName(@Nullable String factoryBeanName);

    /**
     * 返回要使用的bean工厂
     */
    @Nullable
    String getFactoryBeanName();

    /**
     * 指定工厂方法名称（如果有）（对应xml中bean元素的factory-method）
     * <p>
     * 此方法将使用构造函数参数调用，如果未指定任何参数，则不使用任何参数调用。该方法
     * 将在指定的工厂bean(如果有的话)上调用，或者作为本地bean类上的静态方法调用。
     */
    void setFactoryMethodName(@Nullable String factoryMethodName);

    /**
     * 返回工厂方法名称
     */
    @Nullable
    String getFactoryMethodName();

    /**
     * 返回此bean的构造函数参数值
     */
    ConstructorArgumentValues getConstructorArgumentValues();

    /**
     * 是否有构造器参数值设置信息（对应xml中bean元素的<constructor-arg>子元素）
     */
    default boolean hasConstructorArgumentValues() {
        return !getConstructorArgumentValues().isEmpty();
    }

    /**
     * 获取bean定义时配置的属性值设置信息
     */
    MutablePropertyValues getMutableProperties();

    /**
     * 此bean定义中是否有属性设置信息（对应xml中bean元素的<property>子元素）
     */
    default boolean hasPropertyValues() {
        return !getMutableProperties().isEmpty();
    }

    /**
     * 设置bean的初始化方法名称
     */
    void settInitMethodName(@Nullable String initMethodName);

    /**
     * 获取bean的初始化方法名称
     */
    @Nullable
    String getInitMethodName();

    /**
     * 设置bean的销毁方法名称
     */
    void setDestroyMethodName(@Nullable String destroyMethodName);

    /**
     * 获取bean的销毁方法名称
     */
    @Nullable
    String getDestroyMethodName();

    /**
     * 设置bean的role信息
     */
    void setRole(int role);

    /**
     * 获取bean的role信息
     */
    int getRole();

    /**
     * 设置bean的描述信息
     */
    void setDescription(@Nullable String description);

    /**
     * 获取bean的描述信息
     */
    @Nullable
    String getDescription();

    /**
     * 获取bean的类型解析器
     */
    ResolvableType getResolvableType();

    /**
     * 是否是单例bean
     */
    boolean isSingleton();

    /**
     * 是否是多例bean
     */
    boolean isPrototype();

    /**
     * 是否是抽象的（对应xml中bean元素的abstract属性）
     */
    boolean isAbstract();

    /**
     * 返回此bean定义来自资源的描述（以便在出现错误时显示上下文信息）
     */
    @Nullable
    String getResourceDescription();

    /**
     * 返回bean定义信息
     */
    @Nullable
    BeanDefinition getOriginatingBeanDefinition();
}
